﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using log4net;
using ServerControl.Model;
using ServerControl.Model.Enum;

namespace ServerControl.Dal
{
	public class UserDal : DbBase
	{
		private static ILog logger = LogManager.GetLogger("UserDal");
		private static List<User> users = new List<User>();
		public static List<User> Users
		{
			get
			{
				if (users == null || users.Count == 0)
				{
					logger.Info("init users");
					users = Instance.Queryable<User>().ToList();
				}

				return users;
			}
		}

		public static void InitUsers()
		{
			users = Instance.Queryable<User>().ToList();
		}

		public static User GetUserByToken(string token)
		{
			//return Users.Where(u => u.Token == token).FirstOrDefault();
			return Instance
				.Queryable<User>()
				.Where(u => u.Token == token)
				.Single();
		}

		/// <summary>
		/// 获取正常可用的登录用户（过滤掉其他不可用情况）
		/// </summary>
		/// <param name="token">令牌</param>
		/// <returns></returns>
		public static User GetLoginUser(string token)
		{
			//return Users.Where(u => u.Token == token && u.IsEnable == true && u.ExpireDate > DateTime.Now).FirstOrDefault();
			return Instance
				.Queryable<User>()
				.Where(u => u.Token == token && u.IsEnable == true && u.ExpireDate > SqlSugar.SqlFunc.GetDate())
				.Single();
		}

		/// <summary>
		/// 获取正常可用的登录用户（过滤掉其他不可用情况）
		/// </summary>
		/// <param name="userName">用户名</param>
		/// <param name="code">代码</param>
		/// <returns></returns>
		public static User GetLoginUser(string userName, string code)
		{
			//return Users.Where(u => u.UserName == userName && u.Code == code && u.IsEnable == true && u.ExpireDate > DateTime.Now).FirstOrDefault();
			return Instance
				.Queryable<User>()
				.Where(u => u.UserName == userName && u.Code == code && u.IsEnable == true && u.ExpireDate > SqlSugar.SqlFunc.GetDate())
				.Single();
		}

		public static User GetUser(string userName)
		{
			//return Users.Where(u => u.UserName == userName).FirstOrDefault();
			return Instance
				.Queryable<User>()
				.Where(u => u.UserName == userName)
				.Single();
		}

		public static void ResetUsers()
		{
			logger.Info("reset users");
			users = Instance.Queryable<User>().ToList();
		}

		/// <summary>
		/// 新增用户
		/// </summary>
		/// <param name="user"></param>
		/// <param name="userScripts"></param>
		/// <returns></returns>
		public static bool AddUser(User user)
		{
			var isSuccess = Instance
					.Insertable(user)
					.ExecuteCommand() > 0;

			//if (isSuccess)
			//{
			//    ResetUsers();
			//}

			return isSuccess;
		}

		public static bool EditUser(User user)
		{
			var isSuccess = Instance
					.Updateable<User>()
					.SetColumns(u => new User 
					{ 
						MaxCount = user.MaxCount, 
						OnlyData = user.OnlyData,
                        OnlyDataMode = user.OnlyDataMode,
                        ShareData = user.ShareData,
                        ShareDataMode = user.ShareDataMode,
                        Code = user.Code, 
						ExpireDate = user.ExpireDate, 
						Remark = user.Remark })
					//.SetColumns(u => u.MaxCount == user.MaxCount)
					//.SetColumns(u => u.Code == user.Code)
					//.SetColumns(u => u.ExpireDate == user.ExpireDate)
					.SetColumnsIF(!string.IsNullOrEmpty(user.Password), u => u.Password == user.Password)
					.Where(u => u.UserName == user.UserName)
					.ExecuteCommand() > 0;

			//if (isSuccess)
			//{
			//    ResetUsers();
			//}

			return isSuccess;
		}

		public static bool UpdateUserLoginInfo(User user)
		{
			var isSuccess = Instance
				.Updateable(user)
				.UpdateColumns(u => new { u.Token, u.LastLoginIp, u.LastLoginTime })
				.Where(u => u.UserName == user.UserName && u.IsEnable == true && u.ExpireDate > SqlSugar.SqlFunc.GetDate())
				.ExecuteCommand() > 0;

			//if (isSuccess)
			//{
			//    ResetUsers();
			//}

			return isSuccess;
		}

		public static bool UpdateUserState(string userName, UserState userState)
		{
			var isSuccess = Instance
				.Updateable<User>(u => u.IsEnable == (userState == UserState.Enable))
				.Where(u => u.UserName == userName)
				.ExecuteCommand() > 0;

			//if (isSuccess)
			//{
			//    ResetUsers();
			//}

			return isSuccess;
		}

		public static bool ClearUserToken(string token)
		{
			var isSuccess = Instance
				.Updateable<User>()
				.SetColumns(u => new User() { Token = "" })
				.Where(u => u.Token == token)
				.ExecuteCommand() > 0;

			//if (isSuccess)
			//{
			//    ResetUsers();
			//}

			return isSuccess;
		}

		public static bool DeleteUser(string userName)
		{
			var isSuccess = false;
			var instance = Instance;

			try
			{
				instance.BeginTran();				

				instance
					.Deleteable<UserCommand>()
					.Where(uc => uc.UserName == userName)
					.ExecuteCommand();

                isSuccess = Instance
				.Deleteable<User>()
				.Where(u => u.UserName == userName && u.Role != Role.Admin)
				.ExecuteCommand() > 0;

				instance.CommitTran();
			}
			catch (Exception ex)
			{
				instance.RollbackTran();
				logger.Error(ex);
			}

			//if (isSuccess)
			//{
			//    ResetUsers();
			//}

			return isSuccess;
		}

		public static int DeleteUsers(List<string> userNames)
		{
			var successCount = 0;
			var instance = Instance;

			try
			{
				instance.BeginTran();

				

				instance
					.Deleteable<UserCommand>()
					.Where(uc => userNames.Contains(uc.UserName))
					.ExecuteCommand();

                successCount = Instance
				.Deleteable<User>()
				.In(userNames)
				.ExecuteCommand();

				instance.CommitTran();
			}
			catch (Exception ex)
			{
				instance.RollbackTran();
				logger.Error(ex);
			}

			//if (successCount > 0)
			//{
			//    ResetUsers();
			//}

			return successCount;
		}

		public static bool ModifyPassword(string userName, string password)
		{
			var isSuccess = Instance
				.Updateable<User>()
				.SetColumns(u => u.Password == password)
				.Where(u => u.UserName == userName)
				.ExecuteCommand() > 0;

			//if (isSuccess)
			//{
			//    ResetUsers();
			//}

			return isSuccess;
		}

		public static bool ModifyCode(string userName, string code)
		{
			var isSuccess = Instance
				.Updateable<User>()
				.SetColumns(u => u.Code == code)
				.Where(u => u.UserName == userName)
				.ExecuteCommand() > 0;

			//if (isSuccess)
			//{
			//    ResetUsers();
			//}

			return isSuccess;
		}

		public static List<User> GetList(int pageIndex, int pageSize, UserState userState, UserState userExpire, out int records, string userName = "")
		{
			records = 0;
			return Instance
				.Queryable<User>()
				.WhereIF(!string.IsNullOrEmpty(userName), u => u.UserName == userName)
				.WhereIF(userState == UserState.Enable, u => u.IsEnable == true)
				.WhereIF(userState == UserState.Disable, u => u.IsEnable == false)
				.WhereIF(userExpire == UserState.Expired, u => u.ExpireDate <= DateTime.Now)
				.WhereIF(userExpire == UserState.UnExpired, u => u.ExpireDate > DateTime.Now)
				.OrderBy(u => u.AddTime, SqlSugar.OrderByType.Desc)
				.ToPageList(pageIndex, pageSize, ref records);
		}


		public static List<Model.Command> GetUserCommands(string userName)
		{
			return Instance
				.Queryable<UserCommand, Model.Command>((uc, c) => uc.CommandId == c.Id)
				.Where((uc, c) => uc.UserName == userName)
				.Select((uc, c) => c)
				.ToList();
		}

		public static List<Model.Command> GetCommands()
		{
			return Instance
				.Queryable<Model.Command>()
				.ToList();
		}

		public static bool AddCommand(Model.Command command)
		{
			return Instance.Insertable(command).ExecuteCommand() > 0;
		}

		public static bool EditCommand(Model.Command command)
		{
			return Instance.Updateable(command).UpdateColumns(c => new { c.Name, c.Value }).ExecuteCommand() > 0;
		}

		public static bool DeleteCommand(int id)
		{
			var isSuccess = Instance.Deleteable<Model.Command>().Where(c => c.Id == id).ExecuteCommand() > 0;

			if (isSuccess)
			{
				Instance.Deleteable<UserCommand>().Where(uc => uc.CommandId == id).ExecuteCommand();
			}

			return isSuccess;
		}

		public static List<Model.Command> GetCommands(ref int records, int pageIndex, int pageSize)
		{
			records = 0;
			return Instance
				.Queryable<Model.Command>()
				.ToPageList(pageIndex, pageSize, ref records);
		}

		public static void UpdateCommands(string userName, List<int> commandIds)
		{
			var userCommands = new List<UserCommand>();
			commandIds.ForEach(c =>
			{
				userCommands.Add(new UserCommand
				{
					UserName = userName,
					CommandId = c
				});
			});
			Instance.Deleteable<UserCommand>().Where(uc => uc.UserName == userName).ExecuteCommand();

			if (commandIds.Count > 0)
			{
				Instance.Insertable(userCommands).ExecuteCommand();
			}
		}
	}
}
